package org.shagin.jfin.ui.budget.item;

import java.awt.CardLayout;
import java.util.HashMap;
import java.util.Map;

import javax.swing.JPanel;

import org.shagin.jfin.core.Debug;
import org.shagin.jfin.data.model.Account;
import org.shagin.jfin.data.model.CostCenter;
import org.shagin.jfin.data.model.ExpenseRule;
import org.shagin.jfin.data.model.IncomeRule;
import org.shagin.jfin.data.model.OperationCategory;
import org.shagin.jfin.data.model.OperationCategoryLeaf;
import org.shagin.jfin.data.model.TransferRule;
import org.shagin.jfin.ui.budget.item.impl.AbstractBudgetItemView;
import org.shagin.jfin.ui.budget.item.impl.AccountView;
import org.shagin.jfin.ui.budget.item.impl.CostCenterView;
import org.shagin.jfin.ui.budget.item.impl.ExpenseRuleView;
import org.shagin.jfin.ui.budget.item.impl.ExpensesTreeNodeView;
import org.shagin.jfin.ui.budget.item.impl.IncomeRuleView;
import org.shagin.jfin.ui.budget.item.impl.IncomesTreeNodeView;
import org.shagin.jfin.ui.budget.item.impl.OperationCategoryLeafView;
import org.shagin.jfin.ui.budget.item.impl.OperationCategoryView;
import org.shagin.jfin.ui.budget.item.impl.TransferRuleView;
import org.shagin.jfin.ui.budget.item.impl.TransfersTreeNodeView;
import org.shagin.jfin.ui.budget.item.impl.UnknownView;
import org.shagin.jfin.ui.budget.tree.BudgetTreeModel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * The Class BudgetItemViewPane.
 */
@SuppressWarnings("serial")
public class BudgetItemViewPane extends JPanel {

    private static final Logger log = LoggerFactory
            .getLogger(BudgetItemViewPane.class);

    private UnknownView viewUnknown = new UnknownView();
    private AbstractBudgetItemView view;
    private Map<Class<?>, AbstractBudgetItemView> itemViewsHash = new HashMap<Class<?>, AbstractBudgetItemView>();
    private BudgetItemViewRegistry itemViewsRegistry = new BudgetItemViewRegistry();
    private CardLayout cardLayout = new CardLayout();

    /**
     * Instantiates a new budget item view pane.
     */
    public BudgetItemViewPane() {
        super();
        setLayout(cardLayout);
        addView(Object.class, viewUnknown);
        registerViewClasses();
    }

    /**
     * Register view classes.
     */
    private void registerViewClasses() {
        itemViewsRegistry.register(Account.class, AccountView.class);
        itemViewsRegistry.register(CostCenter.class, CostCenterView.class);
        itemViewsRegistry.register(ExpenseRule.class, ExpenseRuleView.class);
        itemViewsRegistry.register(IncomeRule.class, IncomeRuleView.class);
        itemViewsRegistry.register(TransferRule.class, TransferRuleView.class);
        itemViewsRegistry.register(OperationCategory.class,
                OperationCategoryView.class);
        itemViewsRegistry.register(OperationCategoryLeaf.class,
                OperationCategoryLeafView.class);
        itemViewsRegistry.register(BudgetTreeModel.ExpensesTreeNode.class,
                ExpensesTreeNodeView.class);
        itemViewsRegistry.register(BudgetTreeModel.IncomesTreeNode.class,
                IncomesTreeNodeView.class);
        itemViewsRegistry.register(BudgetTreeModel.TransfersTreeNode.class,
                TransfersTreeNodeView.class);

    }

    /**
     * Adds the view.
     * 
     * @param clazz the clazz
     * @param view the view
     */
    private void addView(Class<?> clazz, AbstractBudgetItemView view) {
        itemViewsHash.put(clazz, view);
        add(view, view.getClass().getName());
    }

    /**
     * Gets the view.
     * 
     * @return the view
     */
    public AbstractBudgetItemView getView() {
        return view;
    }

    /**
     * Sets the view.
     * 
     * @param view the new view
     */
    public void setView(AbstractBudgetItemView view) {
        Debug.traceEnter(log);
        this.view = view;
        cardLayout.show(this, view.getClass().getName());
    }

    /**
     * Find or crete.
     * 
     * @param object the object
     * @return the abstract budget item view
     */
    public AbstractBudgetItemView findOrCrete(Object object) {
        Debug.traceEnter(log);
        AbstractBudgetItemView result = itemViewsHash.get(object.getClass());
        if (result == null) {
            result = itemViewsRegistry.findAndCreate(object.getClass());
            if (result != null)
                addView(object.getClass(), result);
        }
        return result == null ? viewUnknown : result;
    }
}
